import pandas as pd
import numpy as np
from datetime import datetime
import os
import math

class getOhlcV:
    def __init__(self, workpath, filepath, targenum, by=['TradeVolume', 'TradeMoney', 'TradeNumber'],
                 method=['constant', 'percent']):
        """
        初始化参数
        :param workpath:工作路径
        :param filepath:读取文件名
        :param by: 选择以交易量、交 易金额、交易笔为基础
        :param method: 选择固定值或者是比例
        :param targenum: 如果是固定值则为数，如果是比例则指定分为多少份
        """
        self.workpath = workpath
        self.filepath = filepath
        self.by = by
        self.method = method
        self.targenum = targenum
        # 过程中会用到的一些类，提前定义占位
        self.SecDatadf = None
        self.filename = None
        self.wheredf = None
        self.df_add = None
        self.data_price = None
        self.cellNum = None

    def insert(self, where):
        # 指定第where行插入一行数据
        df1 = self.wheredf.iloc[:where, :]  # 拆分为两部分
        df2 = self.wheredf.iloc[where:, :]
        self.wheredf = pd.concat([df1, self.df_add, df2], ignore_index=True)  # 拼接在一起

        return self.wheredf  # 这一步必须写

    def shen_conversion(self):
        """
        如遇深交所数据，需要对数据集self.SecDatadf进行一定转换
        :return:
        """
        tag = self.SecDatadf.ExecType == 52  # 提取撤单行数
        self.SecDatadf.drop(tag.index[tag], inplace=True)  # 删除撤单
        self.SecDatadf = self.SecDatadf.reset_index(drop=True)  # 重置索引Index
        # 修改变量命名，使得与上交所一致
        self.SecDatadf.columns = ['ChannelNo', 'TradeIndex', 'MDStreamID', 'BidApplSeqNum',
                                  'OfferApplSeqNum', 'SecurityID', 'SecurityIDSource', 'TradPrice',
                                  'TradVolume', 'ExecType', 'TradTime', 'LocalTime', 'SeqNo']
        # 添加TradeMoney列
        self.SecDatadf['TradeMoney'] = self.SecDatadf.TradPrice * self.SecDatadf.TradVolume

    def get_data(self):
        """
        读取数据
        :return:
        """

        # 此函数用于使用GUI获取文件路径
        import tkinter as tk
        from tkinter import filedialog
        def getLocalFile():
            root = tk.Tk()
            root.withdraw()
            filePath = filedialog.askopenfilename()
            return filePath

        # 如果输入文件路径为空（未指定）
        if self.filepath == '':
            self.filepath = getLocalFile()
        else:
            pass

        self.SecDatadf = pd.read_csv(self.filepath)  # 根据路径读取文件
        self.filename = os.path.split(self.filepath)[-1]  # 获取文件名，用于输出文件命名
        self.SecID = self.SecDatadf['SecurityID'][0]  # 获取股票SecID
        print("已读取{}".format(self.filename))
        # 如果为深交所数据，则进行数据转换
        if 'ApplSeqNum' in self.SecDatadf.columns:
            self.shen_conversion()

    def Call_auction(self):
        """
        处理集合竞价，采用提取的方法
        :return:
        """
        # 提取原始数数据
        self.CAdf = pd.DataFrame({'TradeIndex': self.SecDatadf.TradeIndex, 'TradTime': self.SecDatadf.TradTime})
        # 提取9:25-9:30间的订单
        tag_m = self.CAdf['TradTime'].str.contains('09:2[56789]:[0-9]{2}.[0-9]{3}')

        self.CA_m_df = self.CAdf.loc[tag_m]  # 提取数据
        # 拼接价格
        self.CA_m_df = pd.merge(self.CA_m_df, self.SecDatadf[['TradeIndex', 'TradPrice']], on='TradeIndex', how='left')
        self.SecDatadf.drop(tag_m.index[tag_m], inplace=True)  # 删除提取出的数据
        # 提取14:57-15:00间的订单
        tag_a = self.CAdf['TradTime'].str.contains('14:5[789]:[0-9]{2}.[0-9]{3}|15:00:[0-9]{2}.[0-9]{3}')

        self.CA_a_df = self.CAdf.loc[tag_a]  # 提取数据
        # 拼接价格
        self.CA_a_df = pd.merge(self.CA_a_df, self.SecDatadf[['TradeIndex', 'TradPrice']], on='TradeIndex', how='left')
        self.SecDatadf.drop(tag_a.index[tag_a], inplace=True)  # 删除提取出的数据

        # 判断集合竞价阶段是否存在
        ## 1、两阶段都存在
        if len(self.CA_m_df) > 0 and len(self.CA_a_df) > 0:
            # 提取OHLC价格
            # 构造价格数据data_price
            self.CA_price = pd.DataFrame({'Group': ['CA_m', 'CA_a']})
            # 提取价格

            # self.CA_price.loc[0,['Open','High','Low','Close']] = self.CA_m_df['TradPrice'][0]  # 高开低收价格是一样的，在此取第一个数据
            self.CA_price.loc[0, 'Open'] = self.CA_m_df['TradPrice'][0]
            self.CA_price.loc[0, 'High'] = self.CA_m_df['TradPrice'][0]
            self.CA_price.loc[0, 'Low'] = self.CA_m_df['TradPrice'][0]
            self.CA_price.loc[0, 'Close'] = self.CA_m_df['TradPrice'][0]

            self.CA_price.loc[1, 'Open'] = self.CA_a_df['TradPrice'][0]
            self.CA_price.loc[1, 'High'] = self.CA_a_df['TradPrice'][0]
            self.CA_price.loc[1, 'Low'] = self.CA_a_df['TradPrice'][0]
            self.CA_price.loc[1, 'Close'] = self.CA_a_df['TradPrice'][0]

            # 加入股股票ID
            self.CA_price['SecurityID'] = self.SecID
            # 加入集合竞价表示
            self.CA_price['CA'] = 1

            # 加入时间戳
            self.CA_price.loc[0, 'TradTimeStart'] = self.CA_m_df.loc[0, 'TradTime']
            self.CA_price.loc[1, 'TradTimeStart'] = self.CA_a_df.loc[0, 'TradTime']
            self.CA_price.loc[0, 'TradTimeEnd'] = self.CA_m_df['TradTime'].iloc[-1]
            self.CA_price.loc[1, 'TradTimeEnd'] = self.CA_a_df['TradTime'].iloc[-1]

            self.CA_price.loc[0, 'TradTimeSpan'] = (datetime.strptime(self.CA_price.loc[0, 'TradTimeEnd'],
                                                                      '%H:%M:%S.%f') - datetime.strptime(
                self.CA_price.loc[0, 'TradTimeStart'], '%H:%M:%S.%f')).seconds
            self.CA_price.loc[1, 'TradTimeSpan'] = (datetime.strptime(self.CA_price.loc[1, 'TradTimeEnd'],
                                                                      '%H:%M:%S.%f') - datetime.strptime(
                self.CA_price.loc[1, 'TradTimeStart'], '%H:%M:%S.%f')).seconds
        ##2、只有第一阶段存在
        elif len(self.CA_m_df) > 0:
            self.CA_price = pd.DataFrame({'Group': ['CA_m', 'CA_a']})

            self.CA_price.loc[0, 'Open'] = self.CA_m_df['TradPrice'][0]
            self.CA_price.loc[0, 'High'] = self.CA_m_df['TradPrice'][0]
            self.CA_price.loc[0, 'Low'] = self.CA_m_df['TradPrice'][0]
            self.CA_price.loc[0, 'Close'] = self.CA_m_df['TradPrice'][0]

            # 加入股股票ID
            self.CA_price['SecurityID'] = self.SecID
            # 加入集合竞价表示
            self.CA_price['CA'] = 1

            # 加入时间戳
            self.CA_price.loc[0, 'TradTimeStart'] = self.CA_m_df.loc[0, 'TradTime']
            self.CA_price.loc[0, 'TradTimeEnd'] = self.CA_m_df['TradTime'].iloc[-1]

            self.CA_price.loc[0, 'TradTimeSpan'] = (datetime.strptime(self.CA_price.loc[0, 'TradTimeEnd'],
                                                                      '%H:%M:%S.%f') - datetime.strptime(
                self.CA_price.loc[0, 'TradTimeStart'], '%H:%M:%S.%f')).seconds

        ##3、只有第二阶段存在
        elif len(self.CA_a_df) > 0:
            self.CA_price = pd.DataFrame({'Group': ['CA_m', 'CA_a']})

            self.CA_price.loc[1, 'Open'] = self.CA_a_df['TradPrice'][0]
            self.CA_price.loc[1, 'High'] = self.CA_a_df['TradPrice'][0]
            self.CA_price.loc[1, 'Low'] = self.CA_a_df['TradPrice'][0]
            self.CA_price.loc[1, 'Close'] = self.CA_a_df['TradPrice'][0]

            # 加入股股票ID
            self.CA_price['SecurityID'] = self.SecID
            # 加入集合竞价表示
            self.CA_price['CA'] = 1

            # 加入时间戳
            self.CA_price.loc[1, 'TradTimeStart'] = self.CA_a_df.loc[0, 'TradTime']
            self.CA_price.loc[1, 'TradTimeEnd'] = self.CA_a_df['TradTime'].iloc[-1]

            self.CA_price.loc[1, 'TradTimeSpan'] = (datetime.strptime(self.CA_price.loc[1, 'TradTimeEnd'],
                                                                      '%H:%M:%S.%f') - datetime.strptime(
                self.CA_price.loc[1, 'TradTimeStart'], '%H:%M:%S.%f')).seconds
        ##4、两阶段都不存在
        else:
            self.CA_price = pd.DataFrame({'Group': ['CA_m', 'CA_a']})
            # 加入股股票ID
            self.CA_price['SecurityID'] = self.SecID
            # 加入集合竞价表示
            self.CA_price['CA'] = 1

    def data_process(self):
        if self.by == 'TradeVolume' and self.method == 'percent':
            # 如果为N等分，则计算每一份的交易量是多少
            self.cellNum = self.SecDatadf.TradVolume.sum() / self.targenum

            # 使用分箱思维进行Vgroup划分
            bins = [i * self.cellNum for i in
                    range(0, self.targenum + 1)]  # 设置箱子,形如[0,1,2,3]为设置了3个区间每个为[0,1]、[1,2]、[2,3]
            # 初始化分组数据wheredf
            self.wheredf = pd.DataFrame({'TradeIndex': self.SecDatadf.TradeIndex, 'TradTime': self.SecDatadf.TradTime,
                                         'TradVolume': self.SecDatadf.TradVolume})
            # 利用pd.cut函数进行分箱，参数可选是否包含边界
            self.wheredf['Vgroup'] = pd.DataFrame(
                {'Vgroup': pd.cut(np.cumsum(self.SecDatadf.TradVolume), bins, labels=range(1, self.targenum + 1),
                                  retbins=False,
                                  include_lowest=True, right=True)})
            # 拼接累加数据并
            self.wheredf['cumsum'] = np.cumsum(self.SecDatadf.TradVolume)
            # 对Vgroup做差，以便于后续进行细节处理，方便获得组边界
            self.wheredf['diff'] = self.wheredf[['Vgroup']].diff()

        elif self.by == 'TradeVolume' and self.method == 'constant':
            # 如果是指定了每个组包含多少交易量，则首先计算有多少组
            self.cellNum = math.ceil(self.SecDatadf.TradVolume.sum() / self.targenum)
            print("建议取值区间为{}-{}".format(math.ceil(self.SecDatadf.TradVolume.sum() / 10),
                                        math.ceil(self.SecDatadf.TradVolume.sum() / 100)))

            # 使用分箱思维进行Vgroup划分
            bins = [i * self.targenum for i in range(0, self.cellNum + 1)]  # 设置箱子

            # 初始化分组数据wheredf
            self.wheredf = pd.DataFrame({'TradeIndex': self.SecDatadf.TradeIndex, 'TradTime': self.SecDatadf.TradTime,
                                         'TradVolume': self.SecDatadf.TradVolume})
            # 分箱
            self.wheredf['Vgroup'] = pd.DataFrame(
                {'Vgroup': pd.cut(np.cumsum(self.SecDatadf.TradVolume), bins, labels=range(1, self.cellNum + 1),
                                  retbins=False,
                                  include_lowest=True, right=True)})
            # 拼接累加数据并
            self.wheredf['cumsum'] = np.cumsum(self.SecDatadf.TradVolume)
            # 对Vgroup做差，以便于后续进行细节处理
            self.wheredf['diff'] = self.wheredf[['Vgroup']].diff()

            # 调换数据名,便于下一步处理
            temp = self.cellNum
            self.cellNum = self.targenum
            self.targenum = temp

        elif self.by == 'TradeMoney' and self.method == 'percent':
            # 如果为N等分交易量
            self.cellNum = self.SecDatadf.TradeMoney.sum() / self.targenum

            # 使用分箱思维进行Vgroup划分
            bins = [i * self.cellNum for i in range(0, self.targenum + 1)]  # 设置箱子
            # 初始化分组数据wheredf
            self.wheredf = pd.DataFrame({'TradeIndex': self.SecDatadf.TradeIndex, 'TradTime': self.SecDatadf.TradTime,
                                         'TradVolume': self.SecDatadf.TradVolume})
            # 分箱
            self.wheredf['Vgroup'] = pd.DataFrame(
                {'Vgroup': pd.cut(np.cumsum(self.SecDatadf.TradeMoney), bins, labels=range(1, self.targenum + 1),
                                  retbins=False,
                                  include_lowest=True, right=True)})
            # 拼接累加数据并
            self.wheredf['cumsum'] = np.cumsum(self.SecDatadf.TradeMoney)
            # 对Vgroup做差，以便于后续进行细节处理
            self.wheredf['diff'] = self.wheredf[['Vgroup']].diff()
            pass


        elif self.by == 'TradeMoney' and self.method == 'constant':
            # 计算类别数目
            self.cellNum = math.ceil(self.SecDatadf.TradeMoney.sum() / self.targenum)
            print("建议取值区间为{}-{}".format(math.ceil(self.SecDatadf.TradeMoney.sum() / 10),
                                        math.ceil(self.SecDatadf.TradeMoney.sum() / 100)))

            # 使用分箱思维进行Vgroup划分
            bins = [i * self.targenum for i in range(0, self.cellNum + 1)]  # 设置箱子

            # 初始化分组数据wheredf
            self.wheredf = pd.DataFrame({'TradeIndex': self.SecDatadf.TradeIndex, 'TradTime': self.SecDatadf.TradTime,
                                         'TradVolume': self.SecDatadf.TradVolume})
            # 分箱
            self.wheredf['Vgroup'] = pd.DataFrame(
                {'Vgroup': pd.cut(np.cumsum(self.SecDatadf.TradeMoney), bins, labels=range(1, self.cellNum + 1),
                                  retbins=False,
                                  include_lowest=True, right=True)})
            # 拼接累加数据并
            self.wheredf['cumsum'] = np.cumsum(self.SecDatadf.TradeMoney)
            # 对Vgroup做差，以便于后续进行细节处理
            self.wheredf['diff'] = self.wheredf[['Vgroup']].diff()

            # 调换数据名,便于下一步处理
            temp = self.cellNum
            self.cellNum = self.targenum
            self.targenum = temp


        elif self.by == 'TradeNumber' and self.method == 'percent':
            # N等分交易笔数
            self.cellNum = len(self.SecDatadf) / self.targenum

            # 使用分箱思维进行Vgroup划分
            bins = [i * self.cellNum for i in range(0, self.targenum + 1)]  # 设置箱子
            # 初始化分组数据wheredf
            self.wheredf = pd.DataFrame({'TradeIndex': self.SecDatadf.TradeIndex, 'TradTime': self.SecDatadf.TradTime,
                                         'TradVolume': self.SecDatadf.TradVolume})
            # 分箱
            self.wheredf['Vgroup'] = pd.DataFrame(
                {'Vgroup': pd.cut(pd.Series(list(range(1, len(self.SecDatadf) + 1))), bins,
                                  labels=range(1, self.targenum + 1), retbins=False,
                                  include_lowest=True, right=True)})
            # 拼接累加数据并
            self.wheredf['cumsum'] = pd.Series(list(range(1, len(self.SecDatadf) + 1)))
            # 对Vgroup做差，以便于后续进行细节处理
            self.wheredf['diff'] = self.wheredf[['Vgroup']].diff()

        elif self.by == 'TradeNumber' and self.method == 'constant':
            # 计算类别数目
            self.cellNum = math.ceil(len(self.SecDatadf) / self.targenum)
            print("建议取值区间为{}-{}".format(math.ceil(len(self.SecDatadf) / 10),
                                        math.ceil(len(self.SecDatadf) / 100)))
            # 使用分箱思维进行Vgroup划分
            bins = [i * self.targenum for i in range(0, self.cellNum)]  # 设置箱子

            # 初始化分组数据wheredf
            self.wheredf = pd.DataFrame({'TradeIndex': self.SecDatadf.TradeIndex, 'TradTime': self.SecDatadf.TradTime,
                                         'TradVolume': self.SecDatadf.TradVolume})
            # 分箱
            self.wheredf['Vgroup'] = pd.DataFrame(
                {'Vgroup': pd.cut(pd.Series(list(range(1, len(self.SecDatadf)))), bins, labels=range(1, self.cellNum),
                                  retbins=False,
                                  include_lowest=True, right=True)})
            # 拼接累加数据并
            self.wheredf['cumsum'] = pd.Series(list(range(1, len(self.SecDatadf) + 1)))
            # 对Vgroup做差，以便于后续进行细节处理
            self.wheredf['diff'] = self.wheredf[['Vgroup']].diff()

            # 调换数据名,便于下一步处理
            temp = self.cellNum
            self.cellNum = self.targenum
            self.targenum = temp

    def side_split(self):
        ## 首先对第一行进行处理
        ### 如果第一行的Vgroup为1，则不进行处理，如果不唯一，则需要拆分为多组
        if self.wheredf.iloc[0]['Vgroup'] == 1:
            pass
        else:
            indexi = 0
            for line in range(1, int(self.wheredf.iloc[0]['Vgroup'])):
                self.df_add = pd.DataFrame({'TradeIndex': self.wheredf.iloc[indexi]['TradeIndex'],
                                            'TradTime': self.wheredf.iloc[indexi]['TradTime'],
                                            'TradVolume': self.wheredf.iloc[indexi]['TradVolume'],
                                            'Vgroup': self.wheredf.iloc[indexi]['Vgroup'] - line,
                                            'cumsum': self.wheredf.iloc[indexi]['cumsum'],
                                            'diff': np.nan}, index=[0])
                self.wheredf = self.insert(indexi)  # 使用自定义函数实现插入
                indexi = indexi + 1  # 插入后索引发证改变，需要重新获取indexi
        ## 对两个类别拼接处进行处理
        for i in range(0, len(self.wheredf[self.wheredf['diff'] >= 1].index)):  # 对于diff为1的（也就是组边界处）
            indexi = self.wheredf[self.wheredf['diff'] >= 1].index[i]  # 使用inden遍历边界
            # 取上一个group最后一个和此group第一个的累加数
            cumsum_last = self.wheredf.loc[indexi - 1]['cumsum']
            cumsum_first = self.wheredf.loc[indexi]['cumsum']
            # 判断此边界是否被两个数包含在其中
            if self.wheredf.loc[indexi - 1]['Vgroup'] * self.cellNum < cumsum_first:
                if self.wheredf.loc[indexi - 1]['Vgroup'] * self.cellNum > cumsum_last:  # 如果在其中，则插入复制一行
                    # 构造插入行，注意Vgroup要-1(意为定义为上一组的组别）
                    # 如遇到跳行，则需要插入多行
                    for line in range(1, int(self.wheredf.loc[indexi]['Vgroup']) - int(
                            self.wheredf.loc[indexi - 1]['Vgroup']) + 1):
                        indexi = self.wheredf[self.wheredf['diff'] >= 1].index[i]  # 插入后索引发证改变，需要重新获取indexi
                        self.df_add = pd.DataFrame({'TradeIndex': self.wheredf.loc[indexi]['TradeIndex'],
                                                    'TradTime': self.wheredf.loc[indexi]['TradTime'],
                                                    'TradVolume': self.wheredf.loc[indexi]['TradVolume'],
                                                    'Vgroup': self.wheredf.loc[indexi]['Vgroup'] - line,
                                                    'cumsum': self.wheredf.loc[indexi]['cumsum'],
                                                    'diff': np.nan}, index=[0])
                        self.wheredf = self.insert(indexi)  # 使用自定义函数实现插入

    def get_Ohlc_data(self):
        """
        处理得到OLHC数据
        :return:
        """
        # 拼接价格数据
        self.wheredf = pd.merge(self.wheredf, self.SecDatadf[['TradeIndex', 'TradPrice']], on='TradeIndex', how='left')

        # 轮子函数，配合apply使用
        def myf(df):
            mymax = np.max(df)
            open = df[0]
            mymin = np.min(df)
            close = df[-1]
            return [open, mymax, mymin, close]

        # 构造价格数据data_price
        ## 考虑部分股票交易量稀少（只有一条）
        if len(self.wheredf) == 1:
            # 只写入股票ID
            self.data_price['SecurityID'] = self.SecID
        else:
            # 正常对待
            self.data_price = self.wheredf.groupby('Vgroup').apply(
                lambda x: myf([i for i in x['TradPrice']])).reset_index()
            self.data_price.columns = ['Group', 'Price']  # 重命名
            self.data_price['Open'] = self.data_price['Price'].apply(lambda x: x[0])  # 分别提取OHLC数据
            self.data_price['High'] = self.data_price['Price'].apply(lambda x: x[1])
            self.data_price['Low'] = self.data_price['Price'].apply(lambda x: x[2])
            self.data_price['Close'] = self.data_price['Price'].apply(lambda x: x[3])
            self.data_price.drop(columns='Price', inplace=True)  # 删除原有的Price数据

            # 加入股股票ID
            self.data_price['SecurityID'] = self.SecID

            # 记录分组数据
            ## 组数
            self.data_price['GroupNum'] = len(self.data_price)
            ## 每组单位数量
            self.data_price['cellConstant'] = self.cellNum
            # 记录时间数据
            self.TimeSpan()

        # 拼接集合竞价数据,需要考虑集合竞价阶段
        self.data_price = pd.concat([self.CA_price.loc[self.CA_price.Group == 'CA_m'], self.data_price,
                                     self.CA_price.loc[self.CA_price.Group == 'CA_a']], axis=0)

    def TimeSpan(self):
        """
        处理时间戳，加入每组开始的时间，结束的时间，时间跨度
        注意处理中午休市的时间需要减掉11:30-13:00，共计5400秒
        :return:
        """
        data_timestart = self.wheredf.groupby('Vgroup')['TradTime'].apply(
            lambda x: x.iloc[0]).reset_index()  # 获取每组里面第一笔交易的时间戳
        self.data_price['TradTimeStart'] = data_timestart['TradTime']  # 写入数据中

        data_timeend = self.wheredf.groupby('Vgroup')['TradTime'].apply(
            lambda x: x.iloc[-1]).reset_index()  # 获取每组里面最后一笔交易的时间戳
        self.data_price['TradTimeEnd'] = data_timeend['TradTime']  # 写入数据中

        # 使用每组最后一笔的交易时间戳减去第一笔交易的时间戳的到时间跨度
        data_timespan = self.wheredf.groupby('Vgroup')['TradTime'].apply(
            lambda x: datetime.strptime(x.iloc[-1], '%H:%M:%S.%f') - datetime.strptime(x.iloc[0],
                                                                                       '%H:%M:%S.%f')).reset_index()
        # 将时间跨度转换为以秒为单位，注意中午休市的时间也算上了，所以输出数据中有一个组时间跨度很大
        self.data_price['TradTimeSpan'] = data_timespan['TradTime'].apply(lambda x: x.seconds)  # 转换为秒
        # 减去休市
        tag1 = self.data_price['TradTimeStart'].apply(
            lambda x: datetime.strptime(x, '%H:%M:%S.%f') < datetime(1900, 1, 1, 11, 30, 0))
        tag2 = self.data_price['TradTimeEnd'].apply(
            lambda x: datetime.strptime(x, '%H:%M:%S.%f') > datetime(1900, 1, 1, 13, 0, 0))

        self.data_price.loc[tag1.values & tag2.values, 'TradTimeSpan'] = self.data_price['TradTimeSpan'][
                                                                             tag1.values & tag2.values] - 5400

    def Ohlc_plot(self):
        import mplfinance as mpf
        # 绘OHLCT图
        ## 调用make_mpf_style函数，自定义图表样式
        mc = mpf.make_marketcolors(
            up="red",  # 上涨K线的颜色
            down="green",  # 下跌K线的颜色
            edge="black",  # 蜡烛图箱体的颜色
            volume="blue",  # 成交量柱子的颜色
            wick="black"  # 蜡烛图影线的颜色
        )

        ## 函数返回一个字典，查看字典包含的数据，按照需求和规范调整参数
        style = mpf.make_mpf_style(base_mpl_style="ggplot", marketcolors=mc)

        index1 = pd.date_range("2000-01-01", periods=len(self.data_price), freq="D")  # 设置日期（实际上并不是日期，只是组别）
        OHLC = self.data_price[['Open', 'High', 'Low', 'Close']]
        OHLC.index = index1
        # 注意将datetime_format = '%j',将实现将日期表示为数值，便于查看组别
        mpf.plot(OHLC, type='candle', style=style, datetime_format='%j',
                 title=self.filename + '--' + str(self.by) + '--' + str(self.method) + '--GroupNumber:' + str(
                     len(self.data_price)))  # 使用candlestick_ohlc绘图

    def SaveData(self, data, filename):
        # 此处的filename包括路径和文件后缀，例如'\导出数据\eachticker\Shcategory.csv'

        # 判断类型是否为DF
        if isinstance(data, pd.DataFrame):
            targetsaveData = data
        else:
            targetsaveData = pd.DataFrame(data)

        # save data
        savepath_AnalystConsForeChange = os.path.split(self.workpath + filename)[0]
        savefile_AnalystConsForeChange = self.workpath + filename

        if os.path.exists(savepath_AnalystConsForeChange):

            if not os.path.exists(savefile_AnalystConsForeChange):  # if not a file the write newone
                targetsaveData.to_csv(savefile_AnalystConsForeChange, mode='w', encoding='utf_8_sig', header=True,
                                      index=False)  # write out a new file with header
            else:
                os.remove(savefile_AnalystConsForeChange)  # 删除以前的文件
                targetsaveData.to_csv(savefile_AnalystConsForeChange, mode='w', encoding='utf_8_sig', header=True,
                                      index=False)  # write out a new file with header

                # targetsaveData.to_csv(savefile_AnalystConsForeChange, mode='a', encoding='utf_8_sig', header=False,
                #                       index=False)  # write after a exist file without header

        else:
            os.mkdir(savepath_AnalystConsForeChange)  # no dir exists then make one and save data to csv

            if not os.path.exists(savefile_AnalystConsForeChange):  # if not a file the write newone
                targetsaveData.to_csv(savefile_AnalystConsForeChange, mode='w', encoding='utf_8_sig', header=True,
                                      index=False)  # write out a new file with header
            else:
                os.remove(savefile_AnalystConsForeChange)  # 删除以前的文件
                targetsaveData.to_csv(savefile_AnalystConsForeChange, mode='w', encoding='utf_8_sig', header=True,
                                      index=False)  # write out a new file with header

                # targetsaveData.to_csv(savefile_AnalystConsForeChange, mode='a', encoding='utf_8_sig', header=False,
                #                       index=False)  # write after a exist file without header

    def main_get(self):

        a = datetime.now()  # 开始时间点
        self.get_data()  # 获取数据
        self.Call_auction()  # 处理集合竞价数据
        if len(self.SecDatadf) == 0:
            # 流通性极差无比，连续竞价无交易
            self.data_price = self.CA_price
        else:
            self.data_process()  # 处理数据
            self.side_split()  # 处理组边界
            self.get_Ohlc_data()  # 获取OHLC价格数据
            # 绘图
            self.Ohlc_plot()
            # h = datetime.now()
            # print("绘图用时{}".format(h - g))
        self.SaveData(self.data_price,
                      '\输出数据\\' + str(self.by) + "_" + str(self.method) + "_" + self.filename)  # 统一输出文件名并输出
        b = datetime.now()
        print("用时{}".format(b - a))

